//
//  LJEntry.m
//  LJClientKit
//
//  Created by Anton Chebotaev on 4/10/09.
//  Copyright 2009 AntonChebotaev. All rights reserved.
//

#import "LJEntry.h"

#pragma mark Exceptions
NSString * const LJEntryBadInitException = @"LJEntryBadInitException";

#pragma mark Notifications
NSString * const LJEntryWillPostNotification = @"LJEntryWillPostNotification";
NSString * const LJEntryDidPostNotification  = @"LJEntryDidPostNotification";

@implementation LJEntry

#pragma mark Lifecycle
- (id)init {
	return [self initWithJournal:nil];
	NSLog(@"WARNING: Initializing entry without journal!\n");
}

- (id)initWithJournal:(LJJournal *)aJournal {
	self = [super init];
	if(self) {
		// Init basic data
		journal = aJournal;
		if(journal) {
			userpic = [[journal account] defaultUserpic];
			
			// Used only for unarchiving from data
			journalHash = [journal hash];
		}
		subject = [[NSString alloc] init];
		content = [[NSString alloc] init];
		entryID = 0;
		
		// Init additional data
		tags = [[NSMutableSet alloc] init];
		currentMusic = @"";
		currentMood = @"";
		location = @"";		
		backdatedDate = nil;
		privacyLevel = LJDefaultPrivacy;
		allowedGroups = [[NSMutableSet alloc] init];
		
		// Init Extra properties
		containsAdultContent = LJDefaultAdultContent;
		commentsAllowed = LJDefaultCommentAllowance;
		screenComments = LJDefaultScreening;
		notificationsAllowed = LJDefaultNotificationsAllowance;		
	}
	return self;
}

- (void)dealloc {
	// Release basic data
	[subject release];
	[content release];
	
	// Release additional data
	[tags release];
	[currentMusic release];
	[currentMood release];
	[location release];		
	[self cancelBackdated];
	[allowedGroups release];
	
	// Release superclass
	[super dealloc];
}

#pragma mark Properties

@synthesize subject;
@synthesize content;
@synthesize entryID;
@synthesize journalHash;

@synthesize tags;
@synthesize userpic;
@synthesize currentMusic;
@synthesize currentMood;
@synthesize location;
@synthesize privacyLevel;
@synthesize allowedGroups;
@synthesize backdatedDate;

@synthesize containsAdultContent;
@synthesize commentsAllowed;
@synthesize screenComments;
@synthesize notificationsAllowed;

- (void)setJournal:(LJJournal *)newJournal {
	if (!newJournal || entryID || [[journal name] isCaseInsensitiveLike:[newJournal name]]) {
		return;
	}
	
	[self willChangeValueForKey:@"journal"];
	[self willChangeValueForKey:@"userpic"];

	@synchronized(self){
		if (privacyLevel == LJGroupAllowedEntry) {
			privacyLevel == LJDefaultPrivacy;
			[allowedGroups release];
			allowedGroups = [[NSMutableSet alloc] init];
		}	
		userpic = [[journal account] defaultUserpic];
		journal = newJournal;
		
		// Used only for unarchiving from data
		journalHash = [journal hash];
		
		backdatedDate = nil;
	}
	
	[self didChangeValueForKey:@"journal"];
	[self didChangeValueForKey:@"userpic"];
}
- (LJJournal *)journal {
	return journal;
}

- (void)setBackdated:(NSDate *)aDate {
	[self willChangeValueForKey:@"backdatedDate"];
	@synchronized(self) {
		backdatedDate = [aDate retain];	
	}	
	[self didChangeValueForKey:@"backdatedDate"];
}
- (BOOL)isBackdated {
	@synchronized(self) {
		if (backdatedDate) {
			return true;
		} else {
			return false;
		}
	}
	return false;
}
- (void)cancelBackdated {
	[self willChangeValueForKey:@"backdatedDate"];
	@synchronized(self) {
		[backdatedDate release];
		backdatedDate = nil;
	}	
	[self didChangeValueForKey:@"backdatedDate"];
}

#pragma mark NSCoding implementation
- (id)initWithCoder:(NSCoder *)decoder {
	self = [super init];
	if(self){
		// Unpack basic data
		if ([decoder containsValueForKey:@"LJEntryCodingCorrespondingJournalHash"]) {
			journalHash = [[decoder decodeObjectForKey:@"LJEntryCodingCorrespondingJournalHash"] intValue];
		}
		
		subject = [[decoder decodeObjectForKey:@"LJEntryCodingSubject"] retain];
		content = [[decoder decodeObjectForKey:@"LJEntryCodingContent"] retain];
		entryID = [[decoder decodeObjectForKey:@"LJEntryCodingEntryID"] intValue];
		
		// Unpack additional data
		tags = 		[[decoder decodeObjectForKey:@"LJEntryCodingTags"] retain];
		if ([decoder containsValueForKey:@"LJEntryCodingUserpic"]) {
			userpic =	[decoder decodeObjectForKey:@"LJEntryCodingUserpic"];
		}
		
		currentMusic =	[[decoder decodeObjectForKey:@"LJEntryCodingCurrentMusic"] retain];
		currentMood =	[[decoder decodeObjectForKey:@"LJEntryCodingCurrentMood"] retain];
		location =		[[decoder decodeObjectForKey:@"LJEntryCodingLocation"] retain];
		if ([decoder containsValueForKey:@"LJEntryCodingBackdatedDate"]) {
			backdatedDate = [[decoder decodeObjectForKey:@"LJEntryCodingBackdatedDate"] retain];
		}
		privacyLevel =  [[decoder decodeObjectForKey:@"LJEntryCodingPrivacyLevel"] intValue];
		allowedGroups = [[decoder decodeObjectForKey:@"LJEntryCodingAlowedGroups"] retain];
		
		// Unpack extra data
		containsAdultContent	= [[decoder decodeObjectForKey:@"LJEntryCodingAdultContentAllowance"] intValue];
		commentsAllowed			= [[decoder decodeObjectForKey:@"LJEntryCodingCommentsAllowance"] intValue];
		screenComments			= [[decoder decodeObjectForKey:@"LJEntryCodingScreening"] intValue];
		notificationsAllowed	= [[decoder decodeObjectForKey:@"LJEntryCodingNotificationsAllowance"] intValue];

	}
	return self;
}
- (void)encodeWithCoder:(NSCoder *)encoder {
	// Pack basic data
	[encoder encodeObject:[NSNumber numberWithInt:journalHash] forKey:@"LJEntryCodingCorrespondingJournalHash"];
	[encoder encodeObject:subject				forKey:@"LJEntryCodingSubject"];
	[encoder encodeObject:content				forKey:@"LJEntryCodingContent"];
	[encoder encodeObject:[NSNumber numberWithInt:entryID] forKey:@"LJEntryCodingEntryID"];
	
	// Pack additional data
	[encoder encodeObject:tags					forKey:@"LJEntryCodingTags"];
	[encoder encodeConditionalObject:userpic	forKey:@"LJEntryCodingUserpic"];
	[encoder encodeObject:currentMusic			forKey:@"LJEntryCodingCurrentMusic"];
	[encoder encodeObject:currentMood			forKey:@"LJEntryCodingCurrentMood"];
	[encoder encodeObject:location				forKey:@"LJEntryCodingLocation"];
	if(backdatedDate) {
		[encoder encodeObject:backdatedDate		forKey:@"LJEntryCodingBackdatedDate"];
	}
	[encoder encodeObject:[NSNumber numberWithInt:privacyLevel] forKey:@"LJEntryCodingPrivacyLevel"];
	[encoder encodeObject:allowedGroups			forKey:@"LJEntryCodingAlowedGroups"];
	
	// Pack extra data
	[encoder encodeObject:[NSNumber numberWithInt:containsAdultContent]	forKey:@"LJEntryCodingAdultContentAllowance"];
	[encoder encodeObject:[NSNumber numberWithInt:commentsAllowed]		forKey:@"LJEntryCodingCommentsAllowance"];
	[encoder encodeObject:[NSNumber numberWithInt:screenComments]		forKey:@"LJEntryCodingScreening"];
	[encoder encodeObject:[NSNumber numberWithInt:notificationsAllowed]	forKey:@"LJEntryCodingNotificationsAllowance"];
	
}

#pragma mark NSObject

- (NSString *)description {
	NSMutableString* result = [NSMutableString string];
	[result appendFormat:@"Subject: %@\n", subject];
	[result appendFormat:@"Content: %@\n", content];
	[result appendFormat:@"Journal: %@\n", journal];
	[result appendFormat:@"Journal hash: %d\n", journalHash];
	[result appendFormat:@"Entry ID: %d\n", entryID];
	[result appendFormat:@"Privacy level: %d\n", privacyLevel];
	[result appendFormat:@"Allowed Groups: %@\n", allowedGroups];

	[result appendFormat:@"Current Music: %@\n", currentMusic];
	[result appendFormat:@"Current Mood: %@\n", currentMood];
	[result appendFormat:@"Userpic: %@\n", userpic];
	[result appendFormat:@"Location: %@\n", location];
	
	[result appendFormat:@"Backdated date: %@\n", backdatedDate];	

	return result;
}

#pragma mark Actions
- (void)post:(NSString *)aPassword {
	[[NSNotificationCenter defaultCenter] postNotificationName:LJEntryWillPostNotification object:self];
	@synchronized(self) {
		if (journal) {
			entryID = [[[journal account] server] postEntry:self password:aPassword];
		}
	}
	[[NSNotificationCenter defaultCenter] postNotificationName:LJEntryDidPostNotification object:self];
}

- (NSOperation*)postOperation:(NSString *)password {
	NSInvocationOperation* task = [[[NSInvocationOperation alloc] initWithTarget:self
																	    selector:@selector(post:)
																		  object:password] autorelease];
	return task;
}

- (BOOL)isPostable {
	if (journal) {
		return YES;
	} else {
		return NO;
	}
}

- (BOOL)isPosted {
	return (entryID != 0);
}
@end




























